﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSMock.Implementation;

namespace PSMock
{

	/// <summary>
	/// Option for non typed property mocks, i.e. the argument types have not been specified. 
	/// E.g.
	/// <code>
	/// Mock.Property(mocked.DataProperty))
	///   .Return("mocked");
	/// </code>
	/// </summary>
	public class GetPropertyOption : Option
	{
		public GetPropertyOption(MockedFunction mockedFunction)
			: base(mockedFunction)
		{ }

		/// <summary>
		/// Returns the specified return value for the mocked property.
		/// E.g.
		/// <code>
		/// Mock.Property(mocked.DataProperty))
		///   .Return("mocked");
		/// </code>
		/// </summary>
		/// <typeparam name="TResult">The type of the result.</typeparam>
		/// <param name="returnValue">The return value.</param>
		/// <returns></returns>
		public Option Return<TResult>(TResult returnValue)
		{
			mockedFunction.ReturnValue = returnValue;
			return this;
		}

		/// <summary>
		/// Returns the specified mocked function.
		/// E.g.
		/// <code>
		/// Mock.Property(mocked.DataProperty))
		///   .Return(() => "mocked:" + 1);
		/// </code>
		/// </summary>
		public Option Return<TResult>(Func<TResult> function)
		{
			mockedFunction.Function = function;
			return this;
		}
	}



	/// <summary>
	/// Option for typed property mocks, i.e. the argument types has been specified. 
	/// E.g.
	/// <code>
	/// Mock.Property&gt;string&lt;(mocked.DataProperty)
	///   .Return("mocked");
	/// </code>
	/// </summary>
	public class GetPropertyOption<TResult> : Option
	{
		public GetPropertyOption(MockedFunction mockedFunction)
			: base(mockedFunction)
		{ }

		/// <summary>
		/// Returns the specified return value for the mocked property.
		/// E.g.
		/// <code>
		/// Mock.Property&gt;string&lt;(mocked.DataProperty))
		///   .Return("mocked");
		/// </code>
		/// </summary>
		/// <typeparam name="TResult">The type of the result.</typeparam>
		/// <param name="returnValue">The return value.</param>
		/// <returns></returns>
		public Option Return(TResult returnValue)
		{
			mockedFunction.ReturnValue = returnValue;
			return this;
		}

		/// <summary>
		/// Returns the specified mocked function.
		/// E.g.
		/// <code>
		/// Mock.Property&gt;string&lt;(mocked.DataProperty))
		///   .Return(() => "mocked:" + 1);
		/// </code>
		/// </summary>
		public Option Return(Func<TResult> function)
		{
			mockedFunction.Function = function;
			return this;
		}
	}
}
